﻿using STHPMS1.BLL.B_Core;
using STHPMS1.ICore.I_BLL.Bus;
using STHPMS1.ICore.I_Entity.Info;
using STHPMS1.ICore.I_Entity.Stmpms1;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using STHPMS1.Common.C_Entity.Stmpms1;
using System.Linq;
using System.Collections;
using STHPMS1.ICore;
using STHPMS1.ICore.I_Serv;
using STHPMS1.ICore.I_DAL;
using System.Data;



namespace STHPMS1.BLL.B_Bus
{
    public class Dr_Repair_LarBus : BllBase, IDr_Repair_LarBill
    {
        public void Save<T>(T entity)
            where T : class ,IDr_Repair_Lar
        { 
		this.Scene.Dal.Sthpms1.Save(entity);
        }

        public void Remove(IDr_Repair_Lar entity)
        {
            this.Scene.Dal.Sthpms1.DeleteById<Dr_Repair_Lar>(entity.Id);
        }

        public IEnumerable<T> Get<T>(Expression<Func<T, bool>> predicate, IPagingInfo info)
            where T : class, IDr_Repair_Lar
        {
            return this.Scene.Dal.Sthpms1.Select<T>(predicate, info);
        }

        /// <summary>
        /// 添加大修数据
        /// </summary>
        /// <param name="anniname"></param>
        /// <param name="analy_year"></param>
        public void Insert(string anniname, string analy_year)
        {
            IKeyGenrateService serv = MyApp.Locator.GetInstance<IKeyGenrateService>();
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;
            dao.Delete<Dr_Repair_Lar>(p => p.Anni_Name == anniname && p.Analy_Year == analy_year);

            //获取大修路段
            Expression<Func<Dn_Divi_Planning, bool>> exp = null;
            if (analy_year != null && analy_year.ToString().Length > 0 && analy_year != null && analy_year.ToString().Length > 0)
                exp = pre => pre.Anni_Name == anniname.ToString() && pre.Divi_Time == analy_year.ToString() && pre.Segid_Main == 12003;  
            List<Dn_Divi_Planning> list = this.Scene.Bll.Dn_Divi_Planning.Get<Dn_Divi_Planning>(exp, null).ToList<Dn_Divi_Planning>();

            foreach (Dn_Divi_Planning info in list)
            {
                Dr_Repair_Lar dr_info = new Dr_Repair_Lar();
                dr_info.Id = serv.NewGuid(); //ID
                dr_info.Anni_Name = info.Anni_Name; //资金模型名称
                dr_info.Analy_Year = analy_year; //分析年度
                dr_info.RoadnetId = info.RoadnetId; //路网ID
                dr_info.MainSegid = info.Mainsegid; //决策路段
                dr_info.Rdwayid = info.Rdwayid; //路线编号
                dr_info.Beginmp = info.Beginmp; //起点桩号
                dr_info.Endmp = info.Endmp; //终点桩号

                IB_Invntory ib_invntory = this.Scene.Bll.Dp_Dailymain_Cost.GetB_Invntory(info.Mainsegid);
                int? Rdclass_Dictid = ib_invntory.Rdclass_Dictid; //技术等级
                int? admdiv = ib_invntory.Admdiv;

                #region 大中修方法判断
                //方法类型
                int Type = 1;
                //第一种方法： PCI折减法
                if (info.Segid_Pcidr != null && info.Segid_Pcidr>=0)
                {
                    //① 铣刨沥青层+加铺沥青层
                    if (info.Segid_Pcidr < 30)
                    {
                        Type = 1;
                    }
                    else //② 全结构铣刨+加铺基层+加铺沥青层
                    {
                        Type = 2;
                    }
                }
                if (Type == 1)
                {
                    //第二种方法：PSSI值法
                    if (info.Pssi != null)
                    {
                        //大修结构组合为①
                        if (info.Pssi >= 50)
                        {
                            Type = 1;
                        }
                        else //大修结构组合为②
                        {
                            Type = 2;
                        }
                    }
                }
                #endregion


                //根据技术等级和路面类型 确定设计年限

                Dm_Default_Rating dm_dafault_rating = dao.Single<Dm_Default_Rating>(p => p.Rdclass_Dictid == Rdclass_Dictid);

                //dm_dafault_rating.Year_Asp;

                //根据设计年限 计算设计年限累计当量轴次 
                //double EASL = 1000;  //设计年限内单车道累计当量轴次（万次）
                Dn_Divi_Result result = dao.Single<Dn_Divi_Result>(p => p.Mainsegid == info.Mainsegid);
                //double EASL = this.Scene.Bll.Dm_Modelgroup.GetEaslByModel(result, Convert.ToInt32(analy_year), Convert.ToDouble(dm_dafault_rating.Year_Asp));
                double EASL = this.Scene.Bll.Dm_Modelgroup.GetEaslByModel(result, DateTime.Now.Year + Convert.ToInt32(dm_dafault_rating.Year_Asp));


                //原路面基层厚度
                B_Pmstc b_pmstcinfo= dao.Single<B_Pmstc>(p => p.Rdwayid == ib_invntory.Rdwayid && p.Direction_Dictid == ib_invntory.Direction_Dictid && p.Beginmp <= ib_invntory.Beginmp && p.Endmp >= ib_invntory.Endmp);

                B_Layer b_layer1 = dao.Single<B_Layer>(p => p.Struid == b_pmstcinfo.Struid && p.Layer_Dictid == 55);  //原路基层
                B_Layer b_layer2 = dao.Single<B_Layer>(p => p.Struid == b_pmstcinfo.Struid && p.Layer_Dictid == 55);  //原路底基层
                B_Layer b_layer3 = dao.Single<B_Layer>(p => p.Struid == b_pmstcinfo.Struid && p.Layer_Dictid == 100);  //原路土基层 路基回弹模量

                double? Thick = b_layer1.Thick + b_layer2.Thick; //原路面基层+底基层厚度


                //大修厚度推荐表
                //Dr_Thick_Lar dr_thick_lar = dao.Single<Dr_Thick_Lar>(p => (p.Rdclass_Dictid == Rdclass_Dictid) && p.Easl_Max > EASL && p.Easl_Min <= EASL && p.Thick_Max > b_layer1.Thick && p.Thick_Min <= b_layer1.Thick && p.Mpa_Max > b_layer3.Elamod && p.Mpa_Min <= b_layer3.Elamod);
                Dr_Thick_Lar dr_thick_lar = dao.Single<Dr_Thick_Lar>(p => (p.Rdclass_Dictid == Rdclass_Dictid) && p.Easl_Max > EASL && p.Easl_Min <= EASL && p.Thick_Max > Thick && p.Thick_Min <= Thick && p.Mpa_Max > b_layer3.Elamod && p.Mpa_Min <= b_layer3.Elamod);

                #region 确定材料和厚度

                //行政区域转换为市级
                string stradmdiv = admdiv.ToString().Substring(0, 4) + "00";
                //大中修温度推荐表
                Dr_Temperature dr_temperature = dao.Single<Dr_Temperature>(p => p.Regioncode == Convert.ToInt32(stradmdiv)); 
                //大中修材料推荐表
                Dr_Stru_Recomm dr_stru_recomm = dao.Single<Dr_Stru_Recomm>(p => p.Pave_Type == 12003 && p.Rdclass_Dictid == Rdclass_Dictid && p.Hightemerate_Max > dr_temperature.Max && p.Hightemerate_Min <= dr_temperature.Max && p.Lowtemerate_Max > dr_temperature.Min && p.Lowtemerate_Min <= dr_temperature.Min);

                //① 铣刨沥青层+加铺沥青层
                if (Type == 1) 
                {
                    dr_info.Up_Thick = dr_thick_lar.Pav_Top ??0; //上面层厚度
                    dr_info.Mid_Thick = dr_thick_lar.Pav_Middle ?? 0; //中面层厚度
                    dr_info.Down_Thick = dr_thick_lar.Pav_Low ?? 0; //下面层厚度
                    //dr_info.Up_Thick = 4; //上面层厚度
                    //dr_info.Mid_Thick = 5; //中面层厚度
                    //dr_info.Down_Thick = 6; //下面层厚度

                    dr_info.Up_StruName = dr_stru_recomm.Pav_Top;  //上面层材料
                    dr_info.Mid_StruName = dr_stru_recomm.Pav_Middle; //中面层材料
                    dr_info.Down_StruName = dr_stru_recomm.Pav_Low;  //下面层材料

                }
                else //② 全结构铣刨+加铺基层+加铺沥青层
                {
                    dr_info.Up_Thick = dr_thick_lar.Pav_Top ?? 0; //上面层厚度
                    dr_info.Mid_Thick = dr_thick_lar.Pav_Middle ?? 0; //中面层厚度
                    dr_info.Down_Thick = dr_thick_lar.Pav_Low ?? 0; //下面层厚度
                    //dr_info.Up_Thick = 4; //上面层厚度
                    //dr_info.Mid_Thick = 5; //中面层厚度
                    //dr_info.Down_Thick = 6; //下面层厚度


                    dr_info.JiCeng_Thick = b_layer1.Thick ?? 0; //基层厚度
                    dr_info.DiJiCeng_Thick = b_layer2.Thick ?? 0; //底基层厚度


                    dr_info.Up_StruName = dr_stru_recomm.Pav_Top;  //上面层材料
                    dr_info.Mid_StruName = dr_stru_recomm.Pav_Middle; //中面层材料
                    dr_info.Down_StruName = dr_stru_recomm.Pav_Low;  //下面层材料
                    dr_info.JiCeng_StruName = b_layer1.Stru_Id; //基层材料
                    dr_info.DiJiCeng_StruName = b_layer2.Stru_Id; //底基层材料

                }
                #endregion

                #region 计算总费用

                //计算路段面积
                double? Area = (info.Endmp - info.Beginmp) * ib_invntory.Surfwidth;  //路段总面积平方米
                double? Cost = null;
                //大中修材料价格表
                Dr_Stru_Mate dr_stru_mateInfo1 = dao.Single<Dr_Stru_Mate>(p => p.Stru_Name == dr_info.Up_StruName); //上面层材料单价
                Dr_Stru_Mate dr_stru_mateInfo2 = dao.Single<Dr_Stru_Mate>(p => p.Stru_Name == dr_info.Mid_StruName); //中面层材料单价
                Dr_Stru_Mate dr_stru_mateInfo3 = dao.Single<Dr_Stru_Mate>(p => p.Stru_Name == dr_info.Down_StruName); //下面层材料单价

                double? cost_up = dr_stru_mateInfo1.Stru_Price * Area * dr_info.Up_Thick;  //上面层总价
                double? cost_mid = dr_stru_mateInfo2.Stru_Price * Area * dr_info.Mid_Thick; //中面层总价
                double? cost_down = dr_stru_mateInfo3.Stru_Price * Area * dr_info.Down_Thick; //下面层总价

                if (Type == 1)
                {
                    Cost = cost_up + cost_mid + cost_down;
                }
                else
                {
                    //大中修材料价格表
                    Dr_Stru_Mate dr_stru_mateInfo4 = dao.Single<Dr_Stru_Mate>(p => p.Stru_Name == dr_info.Up_StruName); //上面层材料单价
                    Dr_Stru_Mate dr_stru_mateInfo5 = dao.Single<Dr_Stru_Mate>(p => p.Stru_Name == dr_info.Mid_StruName); //中面层材料单价

                    double? cost_jiceng = dr_stru_mateInfo4.Stru_Price * Area * b_layer1.Thick;  //上面层总价
                    double? cost_dijiceng = dr_stru_mateInfo5.Stru_Price * Area * b_layer2.Thick; //中面层总价

                    Cost = cost_up + cost_mid + cost_down + cost_jiceng + cost_dijiceng;
                }
                dr_info.Cost = Cost/10000;
                //保存到中修结果表
                dao.Save<Dr_Repair_Lar>(dr_info);
                //更新到路网决策路段表
                dao.Update<Dn_Divi_Planning>(new { Project_Id = dr_info.Id, Project_Name = "", Cost = dr_info.Cost, Main_Year = analy_year }, p => p.Anni_Name == anniname && p.Divi_Time == analy_year && p.Mainsegid == info.Mainsegid);
                #endregion
            }
        }


         /// <summary>
        /// 获取龟裂、重度纵向裂缝、重度横向裂缝的病害面积
        /// </summary>
        /// <param name="segid"></param>
        /// <returns></returns>
        public double GetASPArea(string segid)
        {
            return this.Scene.Dal.Sthpms1.Dr_Repair_Lar.GetASPArea(segid);
        }


        /// <summary>
        ///  PCI折减值法
        /// </summary>
        /// <param name="segid"></param>
        /// <returns></returns>
        public double GetPCI(string segid)
        {
            ISthpms1Dao dao = this.Scene.Dal.Sthpms1;

            double C = GetASPArea(segid);

            //基础路段
            IB_Invntory ib_invntory = dao.Dp_Dailymain_Cost.GetB_Invntory(segid);
            //决策路段表
            Dn_Divi_Result ddrinfo= dao.Single<Dn_Divi_Result>(p => p.Mainsegid == segid);

            //路段总面积平方米
            double Area = Convert.ToDouble((ddrinfo.Endmp - ddrinfo.Beginmp) * ib_invntory.Surfwidth);  

            double DR = 100 * (C / Area);

            return 15 * Math.Pow(DR, 0.412);
        }
    }
}
